package com.yangaobo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yangaobo.constant.MC;
import com.yangaobo.dto.AssetsInsertDTO;
import com.yangaobo.dto.AssetsPageDTO;
import com.yangaobo.dto.AssetsUpdateDTO;
import com.yangaobo.entity.Assets;
import com.yangaobo.excel.AssetsExcel;
import com.yangaobo.exception.ServerErrorException;
import com.yangaobo.mapper.AssetsMapper;
import com.yangaobo.service.AssetsService;
import com.yangaobo.util.MinioUtil;
import com.yangaobo.vo.AssetsVO;
import jakarta.annotation.Resource;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 杨奥博
 */
@Service
@CacheConfig(cacheNames = "assets")
public class AssetsServiceImpl implements AssetsService {
    @Resource
    private AssetsMapper assetsMapper;

    @CacheEvict(allEntries = true)
    @Override
    public int insert(AssetsInsertDTO dto) {
        Assets assets = BeanUtil.copyProperties(dto, Assets.class);
        if(StrUtil.isBlank(dto.getInfo())) {
            assets.setInfo("暂无描述");
        }
        assets.setPicture(MC.Assets.DEFAULT_ASSETS);
        assets.setDeleted(0);
        assets.setVersion(0L);
        assets.setUpdated(LocalDateTime.now());
        assets.setCreated(LocalDateTime.now());
        int result = assetsMapper.insert(assets);
        if(result <= 0) {
            throw new ServerErrorException("DB添加失败");
        }
        return result;
    }

    @Cacheable(key = "#p0", condition = "#p0 != null", unless = "#result == null")
    @Override
    public Assets select(Long id) {
        Assets result = assetsMapper.select(id);
        if(ObjectUtil.isNull(result)) {
            throw new ServerErrorException("DB查询失败");
        }
        return result;
    }

    @Cacheable(key = "#root.methodName", unless = "#result == null")
    @Override
    public List<AssetsVO> list() {
        return assetsMapper.list(new AssetsPageDTO())
                .stream()
                .map(assets -> BeanUtil.copyProperties(assets, AssetsVO.class))
                .collect(Collectors.toList());
    }

    @Cacheable(key = "#root.methodName + ':' + #p0.toString()",
            condition = "#p0 != null",
            unless = "#result == null")
    @Override
    public PageInfo<Assets> page(AssetsPageDTO dto) {
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        return new PageInfo<>(assetsMapper.list(dto));
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int update(AssetsUpdateDTO dto) {
        Assets assets = assetsMapper.select(dto.getId());
        if (ObjectUtil.isNull(assets)) {
            throw new ServerErrorException("DB查询失败");
        }
        BeanUtil.copyProperties(dto, assets,
                CopyOptions.create().setIgnoreNullValue(true));
        assets.setUpdated(LocalDateTime.now());
        int result = assetsMapper.update(assets);
        if(result <= 0) {
            throw new ServerErrorException("DB更新失败");
        }
        return result;
    }

    @CacheEvict(allEntries = true)
    @Override
    public int delete(Long id) {
        int result = assetsMapper.delete(id);
        if(result <= 0) {
            throw new ServerErrorException("DB删除失败");
        }
        return result;
    }

    @CacheEvict(allEntries = true)
    @Override
    public int deleteBatch(List<Long> ids) {
        int result = assetsMapper.deleteBatch(ids);
        if(result <= 0) {
            throw new ServerErrorException("DB批量删除失败");
        }
        return result;
    }

    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String uploadPicture(MultipartFile pictureFile, Long id) {
        // 按主键查询记录
        Assets assets = assetsMapper.select(id);
        if (ObjectUtil.isNull(assets)) {
            throw new ServerErrorException("记录不存在");
        }
        // 备份旧文件
        String oldPicture = assets.getPicture();
        // 生成新文件名
        String filename = MinioUtil.randomFilename(pictureFile);
        // DB更新文件名
        assets.setPicture(filename);
        if (assetsMapper.update(assets) <= 0) {
            throw new ServerErrorException("DB更新失败");
        }

        try {
            // MinIO删除旧文件（默认文件不删除）
            if (!MC.Assets.DEFAULT_ASSETS.equals(oldPicture)) {
                MinioUtil.delete(oldPicture, MC.MinIO.ASSETS_DIR, MC.MinIO.BUCKET_NAME);
            }
            // MinIO上传新文件
            MinioUtil.upload(pictureFile, filename, MC.MinIO.ASSETS_DIR, MC.MinIO.BUCKET_NAME);
        } catch (Exception e) {
            throw new ServerErrorException("MinIO操作失败：" + e.getMessage());
        }
        // 返回新文件名
        return filename;
    }

    public List<AssetsExcel> getExcelData() {
        return assetsMapper.list(new AssetsPageDTO())
                .stream()
                .map(assets -> BeanUtil.copyProperties(assets, AssetsExcel.class))
                .collect(Collectors.toList());
    }

}
